﻿namespace LogManager.Console
{
    using LogManager.Core.Models;
    using LogManager.Core.Services;
    using LogManager.Core.Services.Location;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;

    public class HierarchyPainter
    {

        public HashSet<object> _paintedObjects = new HashSet<object>();
        public const string CONTAINER_MARK = "+ ";
        public const string BASE_OFFSET = "  ";
        public const string WAREHOUSE_OFFSET = BASE_OFFSET + BASE_OFFSET;
        public const string PLATEFORM_OFFSET = WAREHOUSE_OFFSET + BASE_OFFSET;
        public const string SERVER_OFFSET = PLATEFORM_OFFSET + BASE_OFFSET;
        public const string LOCATION_OFFSET = SERVER_OFFSET + BASE_OFFSET;
        public const string FOLDERS_OFFSET = LOCATION_OFFSET + BASE_OFFSET;
        public const string FILES_OFFSET = FOLDERS_OFFSET + BASE_OFFSET;

        public ConsoleSpinner Spinner { get; set; }

        private void StartSpinning()
        {
            if (this.Spinner != null)
                this.Spinner.Start();
        }

        private void StopSpinning()
        {
            if (this.Spinner != null)
                this.Spinner.Stop();
        }

        public void Paint(IWarehouse warehouse)
        {
            PaintObject("\n" + WAREHOUSE_OFFSET + CONTAINER_MARK + warehouse.Name, warehouse);
        }

        public void Paint(IPlateform plateform)
        {
            Paint(plateform.ParentWarehouse);

            PaintObject("\n" + PLATEFORM_OFFSET + CONTAINER_MARK + plateform.Name, plateform);
        }

        public void Paint(IServer server)
        {
            Paint(server.ParentPlateform.ParentWarehouse);
            Paint(server.ParentPlateform);

            PaintObject("\n" + SERVER_OFFSET + CONTAINER_MARK + server.Name, server);
        }

        public void Paint(ILocation location)
        {
            Paint(location.ParentServer.ParentPlateform.ParentWarehouse);
            Paint(location.ParentServer.ParentPlateform);
            Paint(location.ParentServer);

            PaintObject("\n" + LOCATION_OFFSET + CONTAINER_MARK + location.Name, location);
        }

        private void PaintObject(string text, object obj)
        {
            if (!_paintedObjects.Contains(obj))
            {
                Console.Write(text);
                _paintedObjects.Add(obj);
            }
        }

        public void PaintSource(LocationArchivingProgress locationArchivingProgress)
        {
            this.PaintNetworkFolder(locationArchivingProgress,
                "Source:" + locationArchivingProgress.Location.FullPathSource,
                locationArchivingProgress.SourceResult
                );
        }

        public void PaintDestination(LocationArchivingProgress locationArchivingProgress)
        {
            this.PaintNetworkFolder(locationArchivingProgress,
                "Destination:" + locationArchivingProgress.Location.FullPathDestination,
                locationArchivingProgress.DestinationResult
                );
        }

        public void PaintNetworkFolder(LocationArchivingProgress locationArchivingProgress, string baseText, SimpleServiceResult result)
        {
            switch (locationArchivingProgress.OperationState)
            {
                case OperationState.Starting:
                    Console.Write("\n" + FOLDERS_OFFSET + "   " + baseText);
                    this.StartSpinning();
                    break;
                case OperationState.Ended:
                    this.StopSpinning();

                    Console.Write("\r" + FOLDERS_OFFSET);
                    if (result.Succeeded)
                    {
                        var prevColor = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write("OK ");
                        Console.ForegroundColor = prevColor;
                        Console.Write(baseText);
                    }
                    else
                    {
                        var prevColor = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write("KO ");
                        Console.ForegroundColor = prevColor;
                        Console.Write(baseText);
                        Console.Write("\n" + FOLDERS_OFFSET);
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write("Error : " + result.Message);
                        Console.ForegroundColor = prevColor;
                    }

                    break;
                default:
                    throw new InvalidEnumArgumentException();
            }
        }

        public void PaintFileResults(LocationArchivingProgress locationArchivingProgress)
        {
            switch (locationArchivingProgress.OperationState)
            {
                case OperationState.Starting:
                    break;
                case OperationState.Ended:

                    Console.Write("\n" + FOLDERS_OFFSET);
                    var result = locationArchivingProgress.LogFilesSearchResult;
                    if (result.Succeeded)
                    {
                        Console.Write("Files to move : " + result.Files.Count);
                    }
                    else
                    {
                        var prevColor = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write("Failed to get Files, Error : " + result.Message);
                        Console.ForegroundColor = prevColor;
                    }
                    break;
                default:
                    throw new InvalidEnumArgumentException();
            }
        }

        public void PaintFileArchiving(LogFileArchivingProgress archivingProgress)
        {
            var logFile = archivingProgress.LogFile;

            switch (logFile.LogFileStep)
            {
                case LogFileArchivingStep.InSource:
                    Console.Write("\n" + FILES_OFFSET);
                    Console.Write("(0 %)   " + logFile.LocationRelativePath);
                    this.StartSpinning();
                    break;
                case LogFileArchivingStep.Archived:
                    Console.Write("\r" + FILES_OFFSET);
                    Console.Write("(50 %)  " + logFile.LocationRelativePath);
                    break;
                case LogFileArchivingStep.SourceCleared:
                    this.StopSpinning();
                    Console.Write("\r" + FILES_OFFSET);
                    var prevColor = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write("OK ");
                    Console.ForegroundColor = prevColor;
                    Console.Write(logFile.LocationRelativePath + "      ");
                    break;
                default:
                    throw new InvalidEnumArgumentException();
            }

            if (logFile.Error != null)
            {
                this.StopSpinning();
                Console.Write("\r" + FILES_OFFSET);
                var prevColor = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("KO ");
                Console.ForegroundColor = prevColor;
                Console.Write(logFile.LocationRelativePath + "      ");
                Console.Write("\n" + FILES_OFFSET);
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("Error : " + logFile.Error.Message);
                Console.ForegroundColor = prevColor;
            }
        }

        public void PaintMailingResult(SimpleServiceResult result)
        {
            var prevColor = Console.ForegroundColor;
            Console.Write("\n\n Sending notifications: ");
            if (result.Succeeded)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write(result.Message);
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write(result.Message);
                Console.Write("\n Error details:" + result.Error.ToString());
            }
            Console.ForegroundColor = prevColor;
        }

        public void PaintStartingOptions(Options options)
        {
            Console.WriteLine("\n Run Mode:" + options.RunMode + "\t Time:" + DateTime.Now);
            Console.WriteLine("--------------------------------------------------------------------------------");
        }

        public void PaintEnd()
        {
            Console.WriteLine("\n End - " + DateTime.Now);
            Console.WriteLine("--------------------------------------------------------------------------------");
        }
    }
}
